package edu.cs.usask.ca.silver.businesslogic.commands.generic;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.UUID;

import edu.cs.usask.ca.silver.api.businesslogic.ScenarioI;
import edu.cs.usask.ca.silver.api.persistence.StorageI;
import edu.cs.usask.ca.silver.businesslogic.ids.FileID;
import edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID;
import edu.cs.usask.ca.silver.businesslogic.ids.ParameterID;
import edu.cs.usask.ca.silver.businesslogic.ids.ParameterSetID;
import edu.cs.usask.ca.silver.businesslogic.ids.ScenarioCollectionID;
import edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID;
import edu.cs.usask.ca.silver.businesslogic.util.SilverAutoManagedObjectFactory;
import edu.cs.usask.ca.silver.businesslogic.util.SilverBLTransactionManager;
import edu.cs.usask.ca.silver.definitions.SupportedModelType;
import edu.cs.usask.ca.silver.persistence.datasource.EmbeddedDerbyStorage;

public class Scenario implements ScenarioI {

	private static final SilverAutoManagedObjectFactory sFactory = new SilverAutoManagedObjectFactory(
			"edu.cs.usask.ca.silver.businesslogic.commands.generic.Scenario");

	public static SilverAutoManagedObjectFactory getObjectPoolFactory() {
		return sFactory;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#createScenario(java
	 * .lang.String, java.lang.String, java.lang.String,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ScenarioCollectionID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ParameterSetID)
	 */
	@Override
	public ScenarioID createGenericScenario(String sName, String sCreator,
			String sDescr, ModelVersionID mvId, ScenarioCollectionID scId,
			ParameterSetID psId, StorageI storage) throws Exception {
		UUID sIdUUID = storage.addScenario(sName, sCreator,
				SupportedModelType.GENERIC.toString(), sDescr,
				mvId.getUUIdVal(), scId.getUUIdVal(), psId.getIdVal());
		return new ScenarioID(sIdUUID);
	}
	
	@Override
	public ScenarioID createVensimScenario(String sName, String sCreator,
			String sDescr, ModelVersionID mvId, ScenarioCollectionID scId,
			ParameterSetID psId, StorageI storage) throws Exception {
		UUID sIdUUID = storage.addScenario(sName, sCreator,
				SupportedModelType.VENSIM.toString(), sDescr,
				mvId.getUUIdVal(), scId.getUUIdVal(), psId.getIdVal());
		return new ScenarioID(sIdUUID);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#
	 * createScenarioAndParameterSet(java.lang.String, java.lang.String,
	 * java.lang.String,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ScenarioCollectionID)
	 */
	@Override
	public ScenarioID createGenericScenarioAndParameterSet(String sName,
			String sCreator, String sDescr, ModelVersionID mvId,
			ScenarioCollectionID scId, StorageI storage) throws Exception {

		boolean error = false;
		ScenarioID result;
		try {
			SilverBLTransactionManager.startTransaction();
			int psIdInt = storage
					.addParameterSet(
							"DESCRIPTION - please fill in descriptions for this scenario");
			UUID sIdInt = storage.addScenario(sName,
					sCreator, SupportedModelType.GENERIC.toString(), sDescr,
					mvId.getUUIdVal(), scId.getUUIdVal(), psIdInt);
			result = new ScenarioID(sIdInt);
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}

		return result;
	}
	
	@Override
	public ScenarioID createVensimScenarioAndParameterSet(String sName,
			String sCreator, String sDescr, ModelVersionID mvId,
			ScenarioCollectionID scId, StorageI storage) throws Exception {

		boolean error = false;
		ScenarioID result;
		try {
			SilverBLTransactionManager.startTransaction();
			int psIdInt = storage
					.addParameterSet(
							"DESCRIPTION - please fill in descriptions for this scenario");
			UUID sIdInt = storage.addScenario(sName,
					sCreator, SupportedModelType.VENSIM.toString(), sDescr,
					mvId.getUUIdVal(), scId.getUUIdVal(), psIdInt);
			result = new ScenarioID(sIdInt);
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getScenarioAsXML(edu
	 * .cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	@Override
	public String getScenarioAsXML(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioAsXML(sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getName(edu.cs.usask
	 * .ca.silver.businesslogic.ids.ScenarioID)
	 */
	public String getName(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioName(sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getDescription(edu
	 * .cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public String getDescription(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioDescription(
				sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getCreator(edu.cs.
	 * usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public String getCreator(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioCreator(sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getType(edu.cs.usask
	 * .ca.silver.businesslogic.ids.ScenarioID)
	 */
	public String getType(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioType(sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getCreationDate(edu
	 * .cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public Date getCreationDate(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioCreationDate(
				sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getCreationTime(edu
	 * .cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public Date getCreationTime(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioCreationTime(
				sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getAssociatedFileIds
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public FileID[] getAssociatedFileIds(ScenarioID sId, StorageI storage) throws Exception {
		ArrayList<UUID> result;
		result = storage.getScenarioAssociatedFileIds(
				sId.getUUIdVal());
		FileID[] ids = new FileID[result.size()];
		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			ids[i++] = new FileID(e.next());
		}
		return ids;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getParentVersionId
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public ModelVersionID getParentVersionId(ScenarioID sId, StorageI storage) throws Exception {
		UUID mvIdInt = storage.getScenarioParentVersionId(
				sId.getUUIdVal());
		return new ModelVersionID(mvIdInt);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#
	 * getParentVersionSimulationType
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public String getParentVersionSimulationType(ScenarioID sId, StorageI storage)
			throws Exception {
		return storage
				.getScenarioParentVersionSimulationType(sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getScenarioCollectionId
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public ScenarioCollectionID getScenarioCollectionId(ScenarioID sId, StorageI storage)
			throws Exception {
		UUID scIdInt = storage
				.getScenarioParentScenarioCollectionId(sId.getUUIdVal());
		return new ScenarioCollectionID(scIdInt);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getScenarioRunUser
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public String getScenarioRunUser(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioRunUser(sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getScenarioRunStartTime
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public Date getScenarioRunStartTime(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioRunStartTime(
				sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getScenarioRunEndTime
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public Date getScenarioRunEndTime(ScenarioID sId, StorageI storage) throws Exception {
		return storage.getScenarioRunEndTime(
				sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getParameterIds(edu
	 * .cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public ParameterID[] getParameterIds(ScenarioID sId, StorageI storage) throws Exception {
		int psIdInt = storage.getScenarioParameterSetId(
				sId.getUUIdVal());
		ArrayList<Integer> result = storage
				.getParameterSetParameterIds(psIdInt);
		ParameterID[] pIds = new ParameterID[result.size()];

		int i = 0;
		Iterator<Integer> e = result.iterator();
		while (e.hasNext()) {
			int temp = e.next();

			pIds[i++] = new ParameterID(temp);
		}

		return pIds;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getParameterSetId(
	 * edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public ParameterSetID getParameterSetId(ScenarioID sId, StorageI storage) throws Exception {
		return new ParameterSetID(storage
				.getScenarioParameterSetId(sId.getUUIdVal()));
	}

	public FileID[] getInputFileIds(ScenarioID sId, StorageI storage) throws Exception {
		ArrayList<UUID> result = storage
				.getScenarioInputFileIds(sId.getUUIdVal());

		FileID[] fIds = new FileID[result.size()];

		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			fIds[i++] = new FileID(e.next());
		}

		return fIds;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getFirstInputFileId
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public FileID getOneInputFileId(ScenarioID sId, StorageI storage) throws Exception {
		return new FileID(storage
				.getScenarioFirstInputFileId(sId.getUUIdVal()));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getOneInputFileName
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public String getOneInputFileName(ScenarioID sId, StorageI storage) throws Exception {
		return (storage.getScenarioFirstInputFileName(sId
				.getUUIdVal()));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getTrajectoryFileIds
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public FileID[] getTrajectoryFileIds(ScenarioID sId, StorageI storage) throws Exception {
		ArrayList<UUID> result = storage
				.getScenarioTrajectoryFileIds(sId.getUUIdVal());

		FileID[] fIds = new FileID[result.size()];

		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			fIds[i++] = new FileID(e.next());
		}
		return fIds;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getAnalysisFileIds
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public FileID[] getAnalysisFileIds(ScenarioID sId, StorageI storage) throws Exception {
		ArrayList<UUID> result = storage
				.getScenarioAnalysisFileIds(sId.getUUIdVal());

		FileID[] fIds = new FileID[result.size()];

		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			fIds[i++] = new FileID(e.next());
		}

		return fIds;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#setName(edu.cs.usask
	 * .ca.silver.businesslogic.ids.ScenarioID, java.lang.String)
	 */
	public boolean setName(ScenarioID sId, String name, StorageI storage) throws Exception {
		return storage.setScenarioName(sId.getUUIdVal(),
				name);
	}
	
	@Override
	public boolean setScenarioAsBaselineToParentModelVersion(ScenarioID sId, StorageI storage) throws Exception {
		return storage.setScenarioAsBaselineScenarioToParentVersion(sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#setDescription(edu
	 * .cs.usask.ca.silver.businesslogic.ids.ScenarioID, java.lang.String)
	 */
	public boolean setDescription(ScenarioID sId, String description, StorageI storage)
			throws Exception {
		return storage.setScenarioDescription(
				sId.getUUIdVal(), description);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#setScenarioCollectionId
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ScenarioCollectionID)
	 */
	public boolean setScenarioCollectionId(ScenarioID sId,
			ScenarioCollectionID scId, StorageI storage) throws Exception {
		return storage.setScenarioScenarioCollectionId(
				sId.getUUIdVal(), scId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#setScenarioRunUser
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID, java.lang.String)
	 */
	public boolean setScenarioRunUser(ScenarioID sId, String user, StorageI storage)
			throws Exception {
		return storage.setScenarioRunUser(sId.getUUIdVal(),
				user);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#setScenarioRunStartTime
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public boolean setScenarioRunStartTime(ScenarioID sId, StorageI storage) throws Exception {
		return storage.setScenarioRunStartTime(
				sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#setScenarioRunEndTime
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public boolean setScenarioRunEndTime(ScenarioID sId, StorageI storage) throws Exception {
		return storage.setScenarioRunEndTime(
				sId.getUUIdVal());
	}

	public boolean deleteScenario(ScenarioID sId, StorageI storage) throws Exception {
		return storage.deleteScenario(sId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getParameterValue(
	 * edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ParameterID)
	 */
	public String getParameterValue(ScenarioID sId, ParameterID pId, StorageI storage)
			throws Exception {
		boolean error = false;
		String result;
		try {
			SilverBLTransactionManager.startTransaction();

			int psId = storage.getScenarioParameterSetId(
					sId.getUUIdVal());
			result = storage.getScenarioParameterValue(psId,
					pId.getIdVal());
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#getParameterComment
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ParameterID)
	 */
	public String getParameterComment(ScenarioID sId, ParameterID pId, StorageI storage)
			throws Exception {
		boolean error = false;
		String result;
		try {
			SilverBLTransactionManager.startTransaction();

			int psId = storage.getScenarioParameterSetId(
					sId.getUUIdVal());
			result = storage.getScenarioParameterComment(
					psId, pId.getIdVal());
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}
		return result;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#setParameterComment
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ParameterID, java.lang.String)
	 */
	public void setParameterComment(ScenarioID sId, ParameterID pId,
			String comment, StorageI storage) throws Exception {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#setType(edu.cs.usask
	 * .ca.silver.businesslogic.ids.ScenarioID,
	 * edu.cs.usask.ca.silver.helper.PackageType)
	 */
	public boolean setType(ScenarioID sId, SupportedModelType type, StorageI storage)
			throws Exception {
		return storage.setScenarioType(sId.getUUIdVal(),
				type.toString());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ScenarioI#isBaseLineScenario
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public boolean isBaseLineScenario(ScenarioID sId, StorageI storage) throws Exception {
		return storage.isBaselineScenario(sId.getUUIdVal());
	}
	
	@Override
	public ScenarioID duplicateScenario(ScenarioID sId, ScenarioCollectionID scId, StorageI storage) throws Exception {
		return new ScenarioID(storage.duplicateScenario(sId.getUUIdVal(), scId.getUUIdVal()));
	}
}
